<?php
namespace app\api\controller;

use app\exception\ApiException;
use app\common\model\LunwenAlipayOrderModel;
use app\common\model\LunwenChargeModel;
use app\common\service\ChargeService;
use app\common\service\OrderService;
use app\common\service\WechatTemplate;
use app\index\model\ZhiniaoUserModel;
use app\index\service\LunwenTransactionRecordServer;
use app\wechat\service\WechatService;
use think\admin\Controller;
use Omnipay\Omnipay;
use think\facade\Db;
use think\Response;

/**
 * Class Index
 * @package app\index\controller
 */
class Charge extends Base
{
    const PAY_ORDER_CHANNEL_ALI = 1;
    const PAY_ORDER_CHANNEL_WX = 2;
    const PAY_ORDER_CHANNEL_ARR = [
        1 => 'AL',
        2 => 'WX',
    ];
    public function getChargeList(){
        $this->checkUserLogin();
        $lunwenCharge = new LunwenChargeModel();
        $result = $this->_query($lunwenCharge->where(['status' => 1])->order('sort desc order desc'))->like("name")->page(false, false);
        $result['list'] = ChargeService::filterChargeList($this->user['id'], $result['list']);
        return $this->returnSuccess($result);
    }
    private function createChargeOrder(int $charge_id, int $order_channel): array
    {
        $charge = LunwenChargeModel::find($charge_id);
        if(!$charge || $charge['status'] != 1){
            throw new ApiException('当前充值金额已失效', '500');
        }
        $subject = sprintf("知鸟AI[%s]储值%s-赠送%s", $this->user['username'], $charge['pay_amount'], $charge['gift_amount']);
        return OrderService::createOrder($this->user, $subject, $order_channel, $charge['pay_amount'], [
            'charge_id' => $charge['id']
        ]);
    }
    /**
     * 储值通过支付宝进行下单
     * @return Response
     * @throws \Omnipay\Common\Exception\InvalidRequestException
     */
    public function aliCharge(){
        $this->checkUserLogin();
        $charge_id = input('charge_id', 0, 'intval');
        
        $order_info = $this->createChargeOrder($charge_id, self::PAY_ORDER_CHANNEL_ALI);
        $gateway = Omnipay::create('Alipay_AopPage');
        $gateway->setSignType(config('alipay.SignType')); // 设置签名类型
        $gateway->setAppId(config('alipay.AppId'));
        $gateway->setPrivateKey(config('alipay.PrivateKey'));
        $gateway->setAlipayPublicKey(config('alipay.AlipayPublicKey'));
        $gateway->setNotifyUrl(config('alipay.NotifyUrl'));
        $gateway->setReturnUrl(config('alipay.ReturnUrl'));
        $subject = $order_info['subject'];
        $out_trade_no = $order_info['out_trade_no'];
        $submitData = [
            'subject'      => $subject,
            'out_trade_no' => $out_trade_no,
            'total_amount' => $order_info['pay_amount'],
            'product_code' => 'FAST_INSTANT_TRADE_PAY',
        ];
        $response = $gateway->purchase()->setBizContent($submitData)->send();
        $url = $response->getRedirectUrl();
        return $this->returnSuccess([
            'url' => $url, 
            'order_channel' => self::PAY_ORDER_CHANNEL_ALI,
            'submitData' => $submitData
        ]);
    }

    /**
     * 储值通过微信支付进行下单
     * @return Response
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionFailedException
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionUnknownException
     * @throws \Endroid\QrCode\Exceptions\ImageTypeInvalidException
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     */
    public function wxCharge()
    {
        $charge_id = input('charge_id', 0, 'intval');
        $order_info = $this->createChargeOrder($charge_id, self::PAY_ORDER_CHANNEL_WX);
        $result = WechatService::WePayOrder()->create([
            'body'             => $order_info['subject'],
            'total_fee'        => $order_info['pay_amount'] * 100,
            'trade_type'       => 'NATIVE',
            // 'notify_url'       => sysuri('api/Charge/notify', [], false, true),
            'notify_url'       => 'http://ai.tinyask.cn/api/Charge/notify',
            'out_trade_no'     => $order_info['out_trade_no'],
            'spbill_create_ip' => $this->request->ip(),
        ]);
        $img_data = $this->_buildQrcBase64($result['code_url']);
        return $this->returnSuccess([
            'url' => $result['code_url'], 
            'order_channel' => self::PAY_ORDER_CHANNEL_WX,
            'img_data' => $img_data
        ]);
    }



    /**
     * 微信支付通知接收处理
     * @return string
     * @throws \WeChat\Exceptions\InvalidResponseException
     */
    public function notify(): string
    {
        $wechat = WechatService::WePayOrder();
        $inputData = $wechat->getNotify();
        // notice data {"appid":"wxcb403ef330d6200b","bank_type":"OTHERS","cash_fee":"1","fee_type":"CNY","is_subscribe":"Y","mch_id":"1640364091","nonce_str":"abvcgiusd7skc7txe2f80homli3alqpn","openid":"osLFO5pNZk0L3OMv6ZJRM5oL3Xic","out_trade_no":"ZNWX77940267391242","result_code":"SUCCESS","return_code":"SUCCESS","sign":"50230F42A510E40086F867273DFD77E9","time_end":"20230321204445","total_fee":"1","trade_type":"NATIVE","transaction_id":"4200001786202303212379233787"}
        // 走支付成功逻辑
        // 开启事务。
        Db::startTrans();
        try {
            $order_info = LunwenAlipayOrderModel::where(['out_trade_no' => $inputData['out_trade_no']])->find();
            if($order_info && $order_info['is_notice'] == 0){
                // 找到订单编号才进行处理。
                $charge = LunwenChargeModel::find($order_info['charge_id']);
                $user = ZhiniaoUserModel::find($order_info['uid']);
                if($charge && $user){
                    // 对充值订单进行处理， 用户储值进行记录。
                    LunwenTransactionRecordServer::recharge($user, $charge['pay_amount'], $charge['gift_amount'], sprintf("微信充值[%s]", $charge['remark']));
                    WechatTemplate::sendRechargeSuccessTemp($user, '微信支付', $charge['remark'], $user->balance);
                }
                // 修改订单通知信息：
                $order_info->notify_time = date('Y-m-d H:i:s');
                $order_info->buyer_id = $inputData['openid'];
                $order_info->trade_status = $inputData['result_code'];
                $order_info->app_id = $inputData['appid'];
                $order_info->update_time = time();
                $order_info->is_notice = 1;
                $order_info->save();
            }
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            $this->app->log->error("wx:pay:" . $e->getMessage() . "\n" . json_encode($inputData));
            Db::rollback();
            return 'fail';
        }
        return 'SUCCESS';
    }
    /**
     * 微信支付，创建用户通知
     * @return string
     * @throws \WeChat\Exceptions\InvalidResponseException
     */
    public function createUserNotify(): string
    {
        $wechat = WechatService::WePayOrder();
        $inputData = $wechat->getNotify();
        // notice data {"appid":"wxcb403ef330d6200b","bank_type":"OTHERS","cash_fee":"1","fee_type":"CNY","is_subscribe":"Y","mch_id":"1640364091","nonce_str":"abvcgiusd7skc7txe2f80homli3alqpn","openid":"osLFO5pNZk0L3OMv6ZJRM5oL3Xic","out_trade_no":"ZNWX77940267391242","result_code":"SUCCESS","return_code":"SUCCESS","sign":"50230F42A510E40086F867273DFD77E9","time_end":"20230321204445","total_fee":"1","trade_type":"NATIVE","transaction_id":"4200001786202303212379233787"}
        // 走支付成功逻辑
        // 开启事务。
        Db::startTrans();
        try {
            $order_info = LunwenAlipayOrderModel::where(['out_trade_no' => $inputData['out_trade_no']])->find();
            $order_info['is_notice'] = 0;
            if($order_info && $order_info['is_notice'] == 0){
                // 进行用户创建
                $extra_data = json_decode($order_info['extra_data'], true);
                if(isset($extra_data['username']) && isset($extra_data['password'])){
                    // 创建用户
                    $user = new ZhiniaoUserModel();
                    $user->username = $extra_data['username'];
                    $user->pid = $extra_data['pid'] ?? 0;
                    // 只可以添加一篇论文
                    $user->aiwrite_num = 1;
                    $user->role = 'role-proxy'; // aiwrite写作角色。
                    $user->expire_time = strtotime('+1 month');
                    $user->password = password_hash($extra_data['password'], PASSWORD_DEFAULT);
                    $user->save();
                    WechatTemplate::sendCreateUserTemp($inputData['openid'], $extra_data['username'], 'http://ai.tinyask.cn/index/User/showOrder?out_trade_no=' . $inputData['out_trade_no']);
                }
                // 修改订单通知信息：
                $order_info->notify_time = date('Y-m-d H:i:s');
                $order_info->buyer_id = $inputData['openid'];
                $order_info->trade_status = $inputData['result_code'];
                $order_info->app_id = $inputData['appid'];
                $order_info->update_time = time();
                $order_info->is_notice = 1;
                $order_info->save();
            }
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            $this->app->log->error("wx:pay:" . $e->getMessage() . "\n" . json_encode($inputData));
            Db::rollback();
            return 'fail';
        }
        return 'SUCCESS';
    }




    /**
     * 创建二维码响应对应
     * @param string $url 二维码内容
     * @return Response
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionFailedException
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionUnknownException
     * @throws \Endroid\QrCode\Exceptions\ImageTypeInvalidException
     */
    private function _buildQrcResponse(string $url): Response
    {
        $qrCode = new \Endroid\QrCode\QrCode();
        $qrCode->setText($url)
               ->setSize(300)
               ->setPadding(20)
               ->setImageType('png');
        return response($qrCode->get(), 200, ['Content-Type' => 'image/png']);
    }

    /**
     * 创建二维码响应对应
     * @param string $url 二维码内容
     * @return String
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionFailedException
     * @throws \Endroid\QrCode\Exceptions\ImageFunctionUnknownException
     * @throws \Endroid\QrCode\Exceptions\ImageTypeInvalidException
     */
    private function _buildQrcBase64(string $url): String
    {
        $qrCode = new \Endroid\QrCode\QrCode();
        $qrCode->setText($url)->setSize(300)->setPadding(20)->setImageType('png');
        return 'data:image/png;base64,' . base64_encode($qrCode->get());
    }



    

    /**
     * 支付宝支付通知接收处理
     * @return string
     * @throws \Omnipay\Common\Exception\InvalidRequestException
     */
    public function payNotice(){
        $gateway = Omnipay::create('Alipay_AopPage');
        $gateway->setSignType(config('alipay.SignType')); // 设置签名类型
        $gateway->setAppId(config('alipay.AppId'));
        $gateway->setPrivateKey(config('alipay.PrivateKey'));
        // dump(config('alipay.AlipayPublicKey'));
        $gateway->setAlipayPublicKey(config('alipay.AlipayPublicKey'));

        $request = $gateway->completePurchase();
        $inputData = array_merge($_POST, $_GET);
        // dump($inputData);

        file_put_contents(SITE_PATH . '/pay.txt', json_encode($inputData));

        $request->setParams($inputData); //Don't use $_REQUEST for may contain $_COOKIE

        /**
         * @var AopCompletePurchaseResponse $response
         */
        try {
            $response = $request->send();
            if($response->isPaid()){

                // 走支付成功逻辑
                // 开启事务。
                Db::startTrans();
                try {
                    $order_info = LunwenAlipayOrderModel::where(['out_trade_no' => $inputData['out_trade_no']])->find();
                    if($order_info && $order_info['is_notice'] == 0){
                        // 找到订单编号才进行处理。

                        $charge = LunwenChargeModel::find($order_info['charge_id']);
                        $user = ZhiniaoUserModel::find($order_info['uid']);

                        if($charge && $user){
                            // 对充值订单进行处理， 用户储值进行记录。
                            LunwenTransactionRecordServer::recharge($user, $charge['pay_amount'], $charge['gift_amount'], sprintf("支付宝充值[%s]", $charge['remark']));
                            WechatTemplate::sendRechargeSuccessTemp($user, '支付宝支付', $charge['remark'], $user->balance);
                        }
                        // 修改订单通知信息：
                        $order_info->notify_time = $inputData['notify_time'];
                        $order_info->buyer_id = $inputData['buyer_id'];
                        $order_info->trade_status = $inputData['trade_status'];
                        $order_info->auth_app_id = $inputData['auth_app_id'];
                        $order_info->app_id = $inputData['app_id'];
                        $order_info->sign_type = $inputData['sign_type'];
                        $order_info->seller_id = $inputData['seller_id'];
                        $order_info->update_time = time();
                        $order_info->is_notice = 1;
                        $order_info->save();
                    }
                    Db::commit();
                } catch (\Exception $e) {
                    $this->app->log->error("ali:pay:" . $e->getMessage() . "\n" . json_encode($inputData));
                    // 回滚事务
                    Db::rollback();
                    die('fail');
                }

                /**
                 * Payment is successful
                 */
                die('success'); //The notify response should be 'success' only
            }else{
                /**
                 * Payment is not successful
                 */
                die('fail'); //The notify response
            }
        } catch (\Exception $e) {
            /**
             * Payment is not successful
             */
            die('fail'); //The notify response
        }


    }
   
}
